package service

import (
	"context"
	"errors"
	"fmt"
	"log"
	"sort"
	"strconv"
	"strings"

	"github.com/beltran/gohive"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
)

type UserService struct{}

type Userinforesp struct {
	UserID string `json:"user_id"`
}

func (u UserService) HandleLoginservice(c *gin.Context) (*Userinforesp, error) {
	var form struct {
		UserID string `form:"user_id" json:"user_id" binding:"required"`
	}
	if err := c.ShouldBind(&form); err != nil {
		return nil, err
	}
	fmt.Println()
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()
	query := fmt.Sprintf("SELECT 1 FROM mirbe.users WHERE user_id = '%s' LIMIT 1", form.UserID)
	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 判断是否有数据返回
	if cursor.HasMore(ctx) {
		// 登录成功，存入 session
		session := sessions.Default(c)
		session.Set("user_id", form.UserID)
		err := session.Save()
		if err != nil {
			log.Println("Session 存储失败:", err)
			return nil, errors.New("内部错误，请稍后重试")
		}

		return &Userinforesp{
			UserID: form.UserID,
		}, nil
	}

	return nil, errors.New("用户不存在")
}

func (u UserService) HandleLogoutservice(c *gin.Context) error {
	// 获取 session
	session := sessions.Default(c)

	// 检查是否已登录
	userID := session.Get("user_id")
	if userID == nil {
		return errors.New("未登录")
	}

	// 清除 session
	session.Delete("user_id")

	// 保存 session 使更改生效
	if err := session.Save(); err != nil {
		log.Println("登出失败:", err)
		return errors.New("登出失败，请稍后重试")
	}

	return nil
}

type Songinforesp struct {
	SongID        string `json:"song_id"`
	ArtistID      string `json:"artist_id"`
	PublishTime   string `json:"publish_time"`
	SongInitPlays string `json:"song_init_plays"`
	Language      string `json:"language"`
	Gender        string `json:"gender"`
}

func (u UserService) HandleGetMusicInfoservice(c *gin.Context) (*Songinforesp, error) {
	var form struct {
		SongID string `form:"song_id" json:"song_id" binding:"required"`
	}

	// 绑定参数
	if err := c.ShouldBind(&form); err != nil {
		return nil, err
	}

	// 连接 Hive
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()
	query := fmt.Sprintf(`
		SELECT song_id, artist_id, publish_time, song_init_plays, language, gender 
		FROM mirbe.songs 
		WHERE song_id = '%s' 
		LIMIT 1
	`, form.SongID)

	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 解析查询结果
	if cursor.HasMore(ctx) {
		var song Songinforesp
		cursor.FetchOne(ctx, &song.SongID, &song.ArtistID, &song.PublishTime, &song.SongInitPlays, &song.Language, &song.Gender)
		if cursor.Err != nil {
			log.Println("读取数据失败:", cursor.Err)
			return nil, errors.New("数据解析失败")
		}
		return &song, nil
	}

	return nil, errors.New("歌曲不存在")
}

type SongDetailResp struct {
	SongID        string `json:"song_id"`
	ArtistID      string `json:"artist_id"`
	PublishTime   string `json:"publish_time"`
	SongInitPlays string `json:"song_init_plays"`
	Language      string `json:"language"`
	Gender        string `json:"gender"`
}

func (u UserService) HandleSearchSongsservice(c *gin.Context) ([]SongDetailResp, error) {
	var form struct {
		SongID           string `form:"song_id" json:"song_id"`
		ArtistID         string `form:"artist_id" json:"artist_id"`
		PublishTimeYear  string `form:"publish_time_year" json:"publish_time_year"`
		PublishTimeMonth string `form:"publish_time_month" json:"publish_time_month"`
		PublishTimeDay   string `form:"publish_time_day" json:"publish_time_day"`
		Language         string `form:"language" json:"language"`
		Gender           string `form:"gender" json:"gender"`
		Page             int    `form:"page" json:"page"`
		Limit            int    `form:"limit" json:"limit"`
	}

	// 绑定请求参数
	if err := c.ShouldBindQuery(&form); err != nil {
		return nil, err
	}

	// 默认分页参数
	if form.Page <= 0 {
		form.Page = 1
	}
	if form.Limit <= 0 {
		form.Limit = 10 // 默认每页 10 条
	}

	// 计算 OFFSET
	offset := (form.Page - 1) * form.Limit

	// 构造查询条件
	var conditions []string

	if form.SongID != "" {
		conditions = append(conditions, fmt.Sprintf("song_id = '%s'", form.SongID))
	}
	if form.ArtistID != "" {
		conditions = append(conditions, fmt.Sprintf("artist_id = '%s'", form.ArtistID))
	}
	if form.PublishTimeYear != "" {
		conditions = append(conditions, fmt.Sprintf("SUBSTR(publish_time, 1, 4) = '%s'", form.PublishTimeYear))
	}
	if form.PublishTimeMonth != "" {
		conditions = append(conditions, fmt.Sprintf("SUBSTR(publish_time, 5, 2) = '%s'", form.PublishTimeMonth))
	}
	if form.PublishTimeDay != "" {
		conditions = append(conditions, fmt.Sprintf("SUBSTR(publish_time, 7, 2) = '%s'", form.PublishTimeDay))
	}
	if form.Language != "" {
		conditions = append(conditions, fmt.Sprintf("language = '%s'", form.Language))
	}
	if form.Gender != "" {
		conditions = append(conditions, fmt.Sprintf("gender = '%s'", form.Gender))
	}

	// 生成 SQL 查询
	query := "SELECT song_id, artist_id, publish_time, song_init_plays, language, gender FROM mirbe.songs"
	if len(conditions) > 0 {
		query += " WHERE " + strings.Join(conditions, " AND ")
	}

	// 添加分页逻辑
	query += fmt.Sprintf(" LIMIT %d OFFSET %d", form.Limit, offset)

	// 连接 Hive
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()
	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 解析查询结果
	var songs []SongDetailResp
	for cursor.HasMore(ctx) {
		var song SongDetailResp
		cursor.FetchOne(ctx, &song.SongID, &song.ArtistID, &song.PublishTime, &song.SongInitPlays, &song.Language, &song.Gender)
		if cursor.Err != nil {
			log.Println("读取数据失败:", cursor.Err)
			return nil, errors.New("数据解析失败")
		}
		songs = append(songs, song)
	}

	return songs, nil
}

func (u UserService) HandleGetRecommendService(c *gin.Context) ([]SongDetailResp, error) {
	// 从 session 获取 user_id
	session := sessions.Default(c)
	userID := session.Get("user_id")

	userIDStr := fmt.Sprintf("%v", userID)

	// 查询 user_active 表，获取出现次数最多的前 20 个 song_id
	queryTopSongs := fmt.Sprintf(`
		SELECT song_id 
		FROM mirbe.user_action
		WHERE user_id = '%s' 
	`, userIDStr)

	// 连接 Hive
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()
	cursor.Exec(ctx, queryTopSongs)
	if cursor.Err != nil {
		log.Println("查询 user_action 失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 解析查询结果，获取 song_id 列表
	var songIDs []string
	for cursor.HasMore(ctx) {
		var songID string
		cursor.FetchOne(ctx, &songID)
		if cursor.Err != nil {
			log.Println("读取 song_id 失败:", cursor.Err)
			return nil, errors.New("数据解析失败")
		}
		songIDs = append(songIDs, songID)
	}

	fmt.Println(songIDs)

	// 如果没有数据，返回空
	if len(songIDs) == 0 {
		return []SongDetailResp{}, nil
	}

	// 构造 SQL 查询 `songs` 表获取详细信息
	querySongs := fmt.Sprintf(`
	SELECT song_id, artist_id, publish_time, song_init_plays, language, gender
	FROM mirbe.songs
	WHERE song_id IN (%s)
	ORDER BY song_init_plays DESC
	`, "'"+strings.Join(songIDs, "','")+"'")

	// 查询 `songs` 表
	cursor.Exec(ctx, querySongs)
	if cursor.Err != nil {
		log.Println("查询 songs 失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 解析查询结果
	var recommendations []SongDetailResp
	for cursor.HasMore(ctx) {
		var song SongDetailResp
		cursor.FetchOne(ctx, &song.SongID, &song.ArtistID, &song.PublishTime, &song.SongInitPlays, &song.Language, &song.Gender)
		if cursor.Err != nil {
			log.Println("解析 songs 失败:", cursor.Err)
			return nil, errors.New("数据解析失败")
		}
		recommendations = append(recommendations, song)
	}

	// 将 SongInitPlays 转换为 int 类型并进行排序
	sort.SliceStable(recommendations, func(i, j int) bool {
		// 将字符串转换为整数，若转换失败则将其视为最小值（或进行其他错误处理）
		playsI, errI := strconv.Atoi(recommendations[i].SongInitPlays)
		if errI != nil {
			playsI = 0 // 默认最小值
		}
		playsJ, errJ := strconv.Atoi(recommendations[j].SongInitPlays)
		if errJ != nil {
			playsJ = 0 // 默认最小值
		}
		return playsI > playsJ // 按照 SongInitPlays 从大到小排序
	})

	return recommendations, nil
}

func (u UserService) HandleGetRecommendByLanguageService(c *gin.Context) ([]SongDetailResp, error) {
	// 从请求中获取 language 参数
	language := c.DefaultQuery("language", "")
	if language == "" {
		return nil, errors.New("language is required")
	}

	// 连接 Hive
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()

	// 查询 songs 表，根据 language 筛选数据
	query := fmt.Sprintf(`
        SELECT song_id, artist_id, publish_time, song_init_plays, language, gender
        FROM mirbe.songs
        WHERE language = '%s'
    `, language)

	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询 songs 失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 解析查询结果
	var recommendations []SongDetailResp
	for cursor.HasMore(ctx) {
		var song SongDetailResp
		cursor.FetchOne(ctx, &song.SongID, &song.ArtistID, &song.PublishTime, &song.SongInitPlays, &song.Language, &song.Gender)
		if cursor.Err != nil {
			log.Println("解析 songs 失败:", cursor.Err)
			return nil, errors.New("数据解析失败")
		}
		recommendations = append(recommendations, song)
	}

	// 如果没有数据，返回空
	if len(recommendations) == 0 {
		return []SongDetailResp{}, nil
	}

	// 将 SongInitPlays 转换为 int 类型并进行排序
	sort.SliceStable(recommendations, func(i, j int) bool {
		// 将字符串转换为整数，若转换失败则将其视为最小值（或进行其他错误处理）
		playsI, errI := strconv.Atoi(recommendations[i].SongInitPlays)
		if errI != nil {
			playsI = 0 // 默认最小值
		}
		playsJ, errJ := strconv.Atoi(recommendations[j].SongInitPlays)
		if errJ != nil {
			playsJ = 0 // 默认最小值
		}
		return playsI > playsJ // 按照 SongInitPlays 从大到小排序
	})

	// 只取前 11 个
	if len(recommendations) > 11 {
		recommendations = recommendations[:11]
	}
	return recommendations, nil
}

type ArtistResp struct {
	ArtistID string `json:"artist_id"`
	Allplays int64  `json:"allplays"`
}

func (u UserService) HandleGetHotArtistsservice(c *gin.Context) ([]ArtistResp, error) {
	// 连接 Hive
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()

	// 查询 artist_id 及其总播放量，并按总播放量降序排序，取前50名
	query := `
		SELECT artist_id, SUM(song_init_plays) AS allplays
		FROM mirbe.songs_new
		GROUP BY artist_id
		ORDER BY allplays DESC
		LIMIT 50
	`

	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询 songs_new 失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}
	log.Println("Hive 查询状态:", cursor.Err)
	// 解析查询结果
	var artists []ArtistResp
	for cursor.HasMore(ctx) {
		var artist ArtistResp
		cursor.FetchOne(ctx, &artist.ArtistID, &artist.Allplays)
		if cursor.Err != nil {
			log.Println("解析 songs_new 失败:", cursor.Err)
			return nil, errors.New("数据解析失败")
		}
		artists = append(artists, artist)
	}

	return artists, nil
}

type SongDetailResp2 struct {
	SongID        string `json:"song_id"`
	ArtistID      string `json:"artist_id"`
	PublishTime   string `json:"publish_time"`
	SongInitPlays int64  `json:"song_init_plays"`
	Language      string `json:"language"`
	Gender        string `json:"gender"`
}

// HandleGetPerRecommendservice 处理个性化推荐

func (u UserService) HandleGetPerRecommendservice(c *gin.Context) ([]SongDetailResp2, error) {
	// 1. 获取 session
	userID := c.DefaultQuery("user_id", "")
	// 2. 连接 Hive
	configuration := gohive.NewConnectConfiguration()
	connection, errConn := gohive.Connect("192.168.100.246", 10000, "NONE", configuration)
	if errConn != nil {
		log.Println("连接 Hive 失败:", errConn)
		return nil, errors.New("数据库连接失败")
	}
	defer connection.Close()

	cursor := connection.Cursor()
	defer cursor.Close()

	ctx := context.Background()

	// 3. 查询用户播放记录
	query := fmt.Sprintf(`
		SELECT song_id 
		FROM mirbe.user_action 
		WHERE user_id = '%s' AND action_type = '1'
	`, userID)

	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询播放记录失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 4. 统计播放次数最多的艺人
	songIDs := []string{}
	for cursor.HasMore(ctx) {
		var songID string
		cursor.FetchOne(ctx, &songID)
		songIDs = append(songIDs, songID)
	}

	if len(songIDs) == 0 {
		return nil, errors.New("用户没有播放记录")
	}
	// 5. 统计播放次数最多的艺人
	var artistIDs []string

	// 遍历 songIDs，通过 song_id 查询对应的 artist_id
	for _, songID := range songIDs {
		query := fmt.Sprintf(`
        SELECT artist_id 
        FROM mirbe.songs_new 
        WHERE song_id = '%s' 
        LIMIT 1
    `, songID)

		cursor.Exec(ctx, query)
		if cursor.Err != nil {
			log.Println("查询 artist_id 失败:", cursor.Err)
			continue
		}

		// 读取查询结果
		var artistID string
		for cursor.HasMore(ctx) {
			cursor.FetchOne(ctx, &artistID)
			if cursor.Err != nil {
				log.Println("读取 artist_id 失败:", cursor.Err)
				continue
			}
			if artistID != "" {
				artistIDs = append(artistIDs, artistID)
			}
		}
	}

	// 输出 artistIDs
	fmt.Println(artistIDs)

	// 6. 统计 artist_id 在 artistIDs 中的出现次数
	artistCount := make(map[string]int)

	for _, artistID := range artistIDs {
		artistCount[artistID]++
	}

	// 7. 找出出现次数最多的 artist_id
	var mostPlayedArtistID string
	maxPlayCount := 0

	for artistID, count := range artistCount {
		if count > maxPlayCount {
			mostPlayedArtistID = artistID
			maxPlayCount = count
		}
	}
	query = fmt.Sprintf(`
    SELECT song_id, artist_id, publish_time, song_init_plays, language, gender 
    FROM mirbe.songs_new 
    WHERE artist_id = '%s'
`, mostPlayedArtistID)

	cursor.Exec(ctx, query)
	if cursor.Err != nil {
		log.Println("查询该艺人歌曲失败:", cursor.Err)
		return nil, errors.New("查询失败")
	}

	// 9. 解析查询结果
	var songDetails []SongDetailResp2

	for cursor.HasMore(ctx) {
		var song SongDetailResp2
		cursor.FetchOne(ctx, &song.SongID, &song.ArtistID, &song.PublishTime, &song.SongInitPlays, &song.Language, &song.Gender)
		songDetails = append(songDetails, song)
	}

	// 返回结果
	return songDetails, nil
}
